/*
 * claplan_controller.cpp
 *
 *  Created on: 1 Nov 2013
 *      Author: Tom Vercauteren
 */

#include "claplan_controller.h"
#include "claplan_view.h"
#include "debug.h"

#include <iostream>
#include <fstream>

using namespace std;

ClaplanController::ClaplanController() :
		view(0), parser(0)
{
}

ClaplanController::~ClaplanController()
{
	removeView();
	removeModels();
	if (parser != 0)
	{
		delete parser;
		parser = 0;
	}
}

int ClaplanController::newClaplanFile(const std::string &file)
{
	cout << "ClaplanController::newClaplanFile called but "
			"is not yet implemented" << endl;
	return 0;
}

int ClaplanController::openClaplanFile(const std::string &file)
{
	cout << "ClaplanController::openClaplanFile called but is "
			"not yet fully implemented." << endl;
	cout << "ClaplanParser will try to parse : " << file << endl;
	if (parser == 0) parser = new ClaplanParser();
	/** Data model */
	ClaplanData* model = new ClaplanData();
	model->file = file;
	parser->setClaplanData(model);

	ifstream input(file.c_str());
	if (!input.is_open())
	{
		cerr << "unable to open file : " << file << endl;
		delete parser;
		parser = 0;
		delete model;
		model = 0;
		return -1;
	}
	int rv = parser->parse(input);
	if (rv != 0)
	{
		cerr << "ClaplanController::openClaplanFile : "
				"parser encountered a problem (return value : " << rv << ")"
				<< endl;
	}

	input.close();
	if (input.is_open())
	{
		cerr << "unable to close file : " << file << endl;
		delete parser;
		parser = 0;
		delete model;
		model = 0;
		return -1;
	}
	delete parser;
	parser = 0;
//	cout << *model << endl;

	addModel(model);

	return 0;
}

void ClaplanController::setView(ClaplanView *view)
{
	this->view = view;
	if (view != 0)
	{
		view->removeController();
		view->setController(this);
	}
}

void ClaplanController::removeView()
{
	if (view != 0) view->removeController();
	view = 0;
}

void ClaplanController::removeModel(ClaplanData *model)
{
	int changed = 0;
	for (unsigned i = 0; i < modelList.size(); i++)
	{
		if (modelList.at(i) == model)
		{
			if (modelList.at(i) != 0)
				cout << "ClaplanController::removeModel : removing "
						<< modelList.at(i)->file << " from the model list"
						<< endl;
			if (view != 0)
			{
				view->removeClaplan(model->file);
			}
			delete modelList.at(i);
			modelList.at(i) = 0;
			modelList.erase(modelList.begin() + i);
			--i;
			changed = 1;
		}
	}
	if (changed == 1) dataChanged();
}

void ClaplanController::removeModels()
{
	for (unsigned i = 0; i < modelList.size(); i++)
	{
		if (modelList.at(i) != 0)
			cout << "ClaplanController::removeModels : removing "
					<< modelList.at(i)->file << " from the model list" << endl;
		if (view != 0)
		{
			view->removeClaplan(modelList.at(i)->file);
		}
		delete modelList.at(i);
		modelList.at(i) = 0;
	}
	modelList.clear();
}

void ClaplanController::addModel(ClaplanData *model)
{
	here;
	if (model == 0) return;
	int addrFound = 0;
	for (unsigned i = 0; i < modelList.size(); i++)
		if (modelList.at(i) != 0 && modelList.at(i)->file == model->file)
		{
			here;
			addrFound = 1;
			return;
		}
	here;
	if (addrFound == 0)
	{
		here;
		cout << "ClaplanController::addModel : adding " << model->file
				<< " to the model list" << endl;
		modelList.push_back(model);
		if (view != 0)
		{
			view->addClaplan(model->file);
			view->addClaplanSection(model->file, "Header");
			view->addClaplanSection(model->file, "Optimization");
			view->addClaplanSection(model->file, "Fractionation");
			if (model->targets.size() > 0)
				view->addClaplanSection(model->file, "Targets");
			if (model->oars.size() > 0)
				view->addClaplanSection(model->file, "Oar");
			if (model->beams.size() > 0)
				view->addClaplanSection(model->file, "Beams");

		}
		dataChanged();
	}
}

ClaplanData* ClaplanController::at(unsigned index)
{
	return (index < modelList.size()) ? modelList.at(index) : 0;
}

unsigned ClaplanController::size() const
{
	return modelList.size();
}

ClaplanDataList* ClaplanController::getModelList()
{
	return &modelList;
}

void ClaplanController::addClaplanDataListener(
		ClaplanDataChangeListener *listener)
{
	int found = 0;
	for (unsigned i = 0; i < listeners.size(); i++)
		if (listeners.at(i) == listener) found = 1;
	if (found == 0) listeners.push_back(listener);
}

void ClaplanController::removeClaplanDataListener(
		ClaplanDataChangeListener *listener)
{
	std::vector<ClaplanDataChangeListener*>::iterator i;
	for (i = listeners.begin(); i != listeners.end(); i++)
		if (*i == listener) listeners.erase(i);
}

void ClaplanController::dataChanged()
{
	cout << "ClaplanController::dataChanged called : " << listeners.size()
			<< " listeners registered" << endl;
	for (unsigned i = 0; i < listeners.size(); i++)
		if (listeners.at(i) != 0) listeners.at(i)->claplanDataChanged();
}

void ClaplanController::setProgramName(const std::string &name)
{
	pname = name;
	if (view != 0)
	{
		view->SetTitle(wxString(pname.c_str(), wxConvUTF8));
	}
}

void ClaplanController::selectionTreeChanged(const std::string &claplan,
		const std::string &section)
{
	if (view != 0)
	{
		string st = "Claplan-editor";
		if (!claplan.empty() && section.empty()) st += " : " + claplan;
		else if (!section.empty())
			st += " : " + string(claplan + " [" + section + "]");
		wxString title(st.c_str(), wxConvUTF8);
		view->SetTitle(title);
	}
}
